123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- using UnityEngine;
- namespace FlatKit {
- public class Buoyancy : MonoBehaviour {
- [Tooltip("The object that contains a Water material.")]
- public Transform water;
- [Space]
- [Tooltip("Range of probing wave height for buoyancy rotation.")]
- public float size = 1f;
- [Tooltip("Max height of buoyancy going up and down.")]
- public float amplitude = 1f;
- [Space, Tooltip("Optionally provide a separate material to get the wave parameters.")]
- public Material overrideWaterMaterial;
- private Material _material;
- private float _speed;
- private float _amplitude;
- private float _frequency;
- private float _direction;
- private Vector3 _originalPosition;
- private Quaternion _originalRotation;
- private void Start() {
- var r = water.GetComponent<Renderer>();
- Debug.Assert(r);
- _material = overrideWaterMaterial != null ? overrideWaterMaterial : r.sharedMaterial;
- Debug.Assert(_material);
- Debug.Assert(_material.HasProperty("_WaveSpeed"));
- _speed = _material.GetFloat("_WaveSpeed");
- _amplitude = _material.GetFloat("_WaveAmplitude");
- _frequency = _material.GetFloat("_WaveFrequency");
- _direction = _material.GetFloat("_WaveDirection");
- var t = transform;
- _originalPosition = t.position;
- _originalRotation = t.rotation;
- }
- private void Update() {
- var positionWS = transform.position;
- var positionOS = water.InverseTransformPoint(positionWS);
- positionWS.y = GetHeightOS(positionOS) + _originalPosition.y;
- transform.position = positionWS;
- var normal = GetNormalWS(positionOS);
- transform.rotation = Quaternion.FromToRotation(Vector3.up, normal) * _originalRotation;
- }
- Vector2 GradientNoiseDir(Vector2 p) {
- p = new Vector2(p.x % 289, p.y % 289);
- float x = (34 * p.x + 1) * p.x % 289 + p.y;
- x = (34 * x + 1) * x % 289;
- x = ((x / 41) % 1) * 2 - 1;
- return (new Vector2(x - Mathf.Floor(x + 0.5f), Mathf.Abs(x) - 0.5f)).normalized;
- }
- float GradientNoise(Vector2 p) {
- Vector2 ip = new Vector2(Mathf.Floor(p.x), Mathf.Floor(p.y));
- Vector2 fp = new Vector2(p.x % 1, p.y % 1);
- float d00 = Vector3.Dot(GradientNoiseDir(ip), fp);
- float d01 = Vector3.Dot(GradientNoiseDir(ip + Vector2.up), fp - Vector2.up);
- float d10 = Vector3.Dot(GradientNoiseDir(ip + Vector2.right), fp - Vector2.right);
- float d11 = Vector3.Dot(GradientNoiseDir(ip + Vector2.one), fp - Vector2.one);
- fp = fp * fp * fp * (fp * (fp * 6f - Vector2.one * 15f) + Vector2.one * 10f);
- return Mathf.Lerp(Mathf.Lerp(d00, d01, fp.y), Mathf.Lerp(d10, d11, fp.y), fp.x);
- }
- private Vector3 GetNormalWS(Vector3 positionOS) {
- Vector3 b = positionOS + Vector3.forward * size;
- b.y = GetHeightOS(b);
- Vector3 c = positionOS + Vector3.right * size;
- c.y = GetHeightOS(b);
- Vector3 n = Vector3.Cross(b - positionOS, c - positionOS).normalized;
- return water.TransformDirection(n);
- }
- private float SineWave(Vector3 positionOS, float offset) {
- // Shader:
- // sin(offset + _Time.z * _WaveSpeed + (pos.x * sin(offset + _WaveDirection) + pos.z *
- // cos(offset + _WaveDirection)) * _WaveFrequency);
- float timez = Time.timeSinceLevelLoad * 2f;
- float s = Mathf.Sin(offset + timez * _speed +
- (positionOS.x * Mathf.Sin(offset + _direction) + positionOS.z *
- Mathf.Cos(offset + _direction)) * _frequency);
- if (_material.IsKeywordEnabled("_WAVEMODE_POINTY")) {
- s = 1.0f - Mathf.Abs(s);
- }
- return s * _amplitude;
- }
- private float GetHeightOS(Vector3 positionOS) {
- float y = SineWave(positionOS, 0.0f);
- if (_material.IsKeywordEnabled("_WAVEMODE_GRID")) {
- y *= SineWave(positionOS, 1.57f);
- }
- y *= amplitude;
- return y;
- }
- }
- }
|